module.exports = (EdtApi) => {
    "use strict";
    let chatId = "", chatIds = null, count = 0, badges, indexdb, dbVersion = 7, handler;
    async function getChatId(times = 0) {
        if (document.querySelector('.chat.tabs-tab.active[data-type="pinned"]')) return chatId;//置顶消息
        let userEl = document.querySelector(".chat.tabs-tab.active .chat-info>.person>.person-avatar");
        let id = userEl?.getAttribute("data-peer-id") || "";
        if (id && id != chatId) return id;
        await EdtApi.sleep(50);
        if (times > 10) return id;
        times++;
        return getChatId(times);
    }
    function openDB(dbName) {
        return new Promise(resolve => {
            let indexedDB = window.indexedDB;
            const request = indexedDB?.open(dbName, dbVersion);
            if (!request) return resolve(null);
            request.onsuccess = event => {
                indexdb = event.target?.result; // 数据库对象
                resolve(indexdb);
            };
            request.onerror = async (event) => {
                let message = event?.target?.error?.message;
                if (message?.includes("existing version (")) {
                    let arr = message.split("existing version (");
                    dbVersion = parseInt(arr[1].split(")")[0]);
                    console.log("dbVersion", dbVersion);
                }
                resolve(await openDB(dbName));
            }
        });
    }
    async function getDbData(storeName) {
        if (!document.querySelector("#page-chats")) return Promise.resolve(null);
        if (!indexdb) await openDB("tweb");
        return new Promise((resolve) => {
            let transaction = indexdb?.transaction([storeName]);
            let objectStore = transaction?.objectStore(storeName);
            let request = objectStore?.getAll();
            if (!request) return resolve(null);
            request.onsuccess = () => {
                resolve(request?.result);
            };
            request.onerror = () => {
                resolve(null);
            };
        });
    }
    async function getChatIds() {
        let ids = [];
        try {
            let users = await getDbData("users");
            let chats = await getDbData("chats");
            let dialogs = await getDbData("dialogs");
            users?.forEach(user => {
                if (!ids.includes(user.id + "")) ids.push(user.id + "");
            });
            chats?.forEach(chat => {
                if (!ids.includes(chat.id + "")) ids.push(chat.id + "");
            });
            dialogs?.forEach(dialog => {
                if (!ids.includes(dialog.peerId + "")) ids.push(dialog.peerId + "");
            });
            chatIds = ids;
        } catch (error) {
            console.error(error);
        }
    }
    function getMsgId(msgBox) {
        let message = EdtApi.closest(msgBox, "div.bubble.is-in,div.bubble.is-out");
        return message?.getAttribute('data-mid');
    }
    function getVoiceFile(peeId, mid) {
        return new Promise(async (resolve, rejects) => {
            let audio = document.getElementById(`audio-${peeId}-${mid}`);
            let url = audio?.getAttribute("src");
            if (!url) rejects("获取语音文件失败！");
            var xhr = new XMLHttpRequest();
            xhr.withCredentials = true;
            xhr.open("GET", url, true);
            xhr.setRequestHeader("Range", "bytes=0-"); //下载全部
            xhr.responseType = "arraybuffer"; // response 是一个包含二进制数据的 JavaScript ArrayBuffer。
            xhr.onload = function () {
                if (xhr.status === 206) {// 处理成功响应
                    resolve(xhr.response);
                } else {
                    // 处理错误响应
                    console.error("请求失败：" + xhr.status);
                    rejects("获取语音文件失败:" + xhr.status);
                }
            };
            xhr.send();
        });
    }

    function getNodeContent(node, status) {
        let text = "";
        switch (node.nodeName) {
            case "#text":
                text = node.textContent;
                if (!status.hasText) status.hasText = !!node.textContent;
                break;
            case "IMG":
                text = node.alt;
                break;
            case "BR":
                text = "\n";
                break;
            case "A":
                text = node.textContent;
                if (!status.hasText) status.hasText = !!node.textContent;
                break;
            case "STRONG":
                node.childNodes?.forEach((child) => {
                    text += getNodeContent(child, status);
                });
                break;
            case "EM":
                text = node.textContent;
                if (!status.hasText) status.hasText = !!node.textContent;
                break;
            case "SPAN":
                if (!node.classList.contains("time")) {//忽略时间
                    text = node.textContent;
                    if (!status.hasText) status.hasText = !!node.textContent;
                }
                break;
            default:
                text = node.textContent;
                if (!status.hasText) status.hasText = !!node.textContent;
                break;
        }
        return text;
    }
    return {
        config: {
            friendList: 'div.tabs-tab.chatlist-parts,ul.chatlist,.search-super-content-container',
            chat: '#column-center',
            input: '.chat.tabs-tab.active .input-message-container>.input-message-input',
            msgBox: '.chat.tabs-tab.active .bubbles',
            inMsg: '.chat.tabs-tab.active .bubble.is-in:not(.voice-message) .message.spoilers-container:not(.trans-inited)',
            outMsg: '.chat.tabs-tab.active .bubble.is-out:not(.voice-message) .message.spoilers-container:not(.trans-inited)',
            allMsg: ".chat.tabs-tab.active .bubble .message.spoilers-container",
            voiceMsg: '.chat.tabs-tab.active .bubble.voice-message .message.spoilers-container:not(.trans-inited)',
            outVoice: {
                selector: ".bubble.voice-message.is-out",
                level: 10,
            },
            sendBtn: '.chat.tabs-tab.active button.send',
            setting: '.chat.tabs-tab.active .chat-input .input-message-container',
            inputType: "input",
            tips: {
                in: ".chat.tabs-tab.active .chat-info .content",
                out: ".chat.tabs-tab.active div.chat-input-container.chat-input-main-container",
            },
            files: {
                sendBtn: ".popup-send-photo.active .popup-input-container>button",
                event: "mousedown",
            },
            placeholder: {
                selector: ".chat.tabs-tab.active .input-message-container>.input-field-placeholder",
            },
            userInfo: {
                selector: "div.btn-menu-item",
                level: 6
            },
            crm: {
                listener: '#main-columns .sidebar-content',
                top: 'div.sidebar-header.topbar.is-pinned-message-shown div.chat-info .user-title>.peer-title,div.sidebar-header.topbar div.chat-info .user-title',
            },
            contextmenu: {
                enable: true,
                selector: "div.media-viewer-whole.active"
            },
            extra: {//其他会触发对话框变动的情况处理
                selector: ".sidebar-close-button,.anchor-url,.avatar.user-avatar,.avatar-photo,.chatlist>a.chatlist-chat,div.chat.tabs-tab.active div.sidebar-header div.chat-utils>button.chat-pinlist",
                level: 20,
                delay: 600
            },
            autoCount: 20,
            mainRequest: true,
            inputType: "input"
        },
        init(_handler) {
            handler = _handler;
            // EdtApi.queryWait({ selector: "button.sidebar-tools-button" }).then((view) => {
            //     view?.click();
            //     let btns = view.querySelectorAll("div.btn-menu-item");
            //     console.log("btns", btns);
            //     // btns?.forEach(btn => {
            //     //     if (btn.textContent.includes("Settings")) btn.click();
            //     // });
            // });
        },
        handlerEnter(e) {
            if (e.isTrusted) return;
            let inputEl = document.querySelector(this.config.input);
            if (inputEl && handler.canSend(inputEl, handler.settingInfo)) {
                inputEl.focus();
                let sendBtn = document.querySelector(this.config.sendBtn);
                sendBtn?.click();
                inputEl.removeAttribute("transleted");
                inputEl.removeAttribute("trans-result");
            }
        },
        getUnread() {
            count = 0;
            let newEl;
            badges = document.querySelectorAll("#main-columns ul.chatlist>a:not(.is-muted) .dialog-subtitle .unread");
            badges?.forEach(badge => {
                newEl = badge.querySelector(".Jw1oQFdk");
                count += EdtApi.safeParseInt(newEl ? newEl.textContent : badge.textContent);
            });
            return count;
        },
        getItemByChatId(chatId) {
            return document.querySelector(`.transition-item.active ul.chatlist>a.chatlist-chat[href="#${chatId}"]`);
        },
        getChatIds() {
            let ids = chatIds;
            getChatIds();
            console.log("chatIds", ids);
            return ids;
        },
        isCanScroll(e) {
            if (!e) return false;
            let target = e.srcElement || e.target;
            if (!target) return false;
            if (document.querySelector(".input-search>input.input-search-input")?.value) return false;
            if (document.querySelector(this.config.friendList)?.contains(target)) return true;
            return false;
        },
        getChatInfo(e) {
            let canScroll = this.isCanScroll(e);//必须在此处判断，不然页面元素可能会变动
            return new Promise(async (resolve) => {
                chatId = await getChatId();
                console.log("getChatInfo:::", chatId);
                resolve({ id: chatId, isGroup: chatId?.includes("-") });
                canScroll && this.scrollToBottom();
            });
        },
        getChatTitle(chatEl = document) {
            let titleEl = chatEl.querySelector(
                "div.sidebar-header.topbar.is-pinned-message-shown div.chat-info .user-title>.peer-title,div.sidebar-header.topbar div.chat-info .user-title>.peer-title"
            );
            if (!titleEl) return "";
            if (!titleEl.querySelector(".emoji")) return titleEl.textContent || "";
            let title = "";
            titleEl.childNodes?.forEach((child) => {
                if (child.nodeName == "#text") {
                    title += child.textContent || "";
                } else if (child.nodeName == "IMG") {
                    title += child.alt || "";
                }
            });
            return title;
        },
        getText(msgBox) {
            let texts = [],
                text = "", status = {
                    hasText: false
                };
            try {
                let message = msgBox.querySelector("span.translatable-message");
                let childNodes = message?.childNodes || msgBox.childNodes;
                childNodes?.forEach((child) => {
                    text = getNodeContent(child, status);
                    texts.push(text);
                });
            } catch (error) {
                console.error(error);
            }
            if (!status.hasText) return "";
            return texts.join("\n");
        },
        getIptText(inputEl) {
            return inputEl?.textContent || "";
        },
        getIptMsg(inputEl) {
            if (!inputEl) return "";
            let value = "";
            try {
                value = inputEl.textContent;
                if (!value) return "";//纯表情不翻译
                value = "";
                inputEl.childNodes?.forEach((child) => {
                    if (child.nodeName == "#text") {
                        value += child.textContent;
                    } else if (child.nodeName == "IMG") {
                        value += child.alt;
                    } else if (child.nodeName == "BR") {
                        value += "\n";
                    } else if (child.nodeName == "SPAN") {
                        value += child.textContent;
                    } else value += child.textContent;
                });
            } catch (error) {
                console.error(error);
            }
            return value;
        },
        getVoice(msgBox) {
            return new Promise(async (resolve, reject) => {
                let peeId = await getChatId();
                let msgId = getMsgId(msgBox);
                getVoiceFile(peeId, msgId).then(file => {
                    resolve({
                        file,
                        msgId,
                        type: "audio/ogg",
                        name: `${msgId}.ogg`
                    });
                }).catch((err) => {
                    reject(err?.message || "获取语音文件失败！");
                });
            });
        },
        getMsgId(msgBox) {
            return getMsgId(msgBox);
        },
        beforeSend({ handler }) {
            //发送前处理特殊情况
            let obj = {
                result: true,
                fileInput: null,
            };
            return new Promise((resolve) => {
                let fileModal = document.querySelector(".popup-send-photo.active");
                if (!fileModal) return resolve(obj);
                let fileInput = fileModal.querySelector(".popup-input-inputs .input-message-input");
                if (!fileInput) return resolve(obj);
                obj.fileInput = fileInput;
                let msg = this.getIptMsg(fileInput);
                if (!handler.sendTrans(msg)) return resolve(obj);
                handler.transToInput(fileInput, msg).then((result) => {
                    obj.result = result;
                    resolve(obj);
                }).catch((error) => {
                    handler.showLoading({
                        msg: error.message || "翻译失败！",
                        type: "error",
                    });
                    obj.result = false;
                    resolve(obj);
                });
            });
        },
        scrollToBottom() {
            // let num = 0, el, timer = setInterval(() => {
            //     el = document.querySelector(".chat.tabs-tab.active .bubbles");
            //     if (el) el.scrollTop = el.scrollHeight;
            //     num++;
            //     if (num >= 2) {
            //         clearInterval(timer);
            //         timer = null;
            //         el = null;
            //     }
            // }, 200);
            setTimeout(() => {
                let btn = document.querySelector("button.bubbles-go-down");
                btn?.click();
            }, 500);
        },
        reHandlerUserInfo(times) {
            if (times < 10) {
                times++;
                setTimeout(() => {
                    this.handlerUserInfo(times);
                }, 5000);
            }
        },
        handlerUserInfo() {
            EdtApi.queryWait({ selector: "div.sidebar-content div.profile-content.is-me" }).then(async (view) => {
                if (view) {
                    let avatarEl = view.querySelector("div.profile-avatars-avatars img.avatar-photo");
                    let avatar = avatarEl?.getAttribute("src") || "";
                    let accountEl = view.querySelector("div.sidebar-left-section-content>div.row:nth-child(1)>div.row-title");
                    let account = accountEl?.textContent || "";
                    if (account) {
                        account = account.replace(/ /g, "");
                    }
                    let userNameEl = view.querySelector("div.sidebar-left-section-content>div.row:nth-child(2)>div.row-title");
                    let userName = userNameEl?.textContent || "";
                    if (avatar && avatar.startsWith("blob:")) {
                        avatar && (avatar = await EdtApi.urlToDataUrl(avatar));
                    }
                    let userInfo = {
                        avatar,
                        userName,
                        account
                    };
                    localStorage.setItem("user-info", JSON.stringify(userInfo));
                    EdtApi.sendToHost('user-info', userInfo);
                }
            }).catch((error) => { console.error(error); });
        },
        getUserInfo() {
            let userInfo = localStorage.getItem("user-info");
            if (userInfo) {
                userInfo = JSON.parse(userInfo);
            } else {
                userInfo = {
                    avatar: "",
                    userName: "",
                    account: ""
                }
            }
            return userInfo;
        }
    }
};